#include "eltag.h"
#include <QPaintEvent>
#include <QPainter>
#include "../basic/elbutton.h"

const int ElTag::Padding_Lr = 10;
const int ElTag::Padding_Tb = 8;
const int ElTag::Icon_Spacing = 8;

ElTag::ElTag(QWidget *parent)
    : ElComponent{parent}
{
    initPalette();
}

ElTag::ElTag(const QString &content, QWidget *parent)
    : ElTag{parent}
{
    setContent(content);
}

void ElTag::paintEvent(QPaintEvent *e)
{
    QPainter painter(this);
    QRectF br;
    painter.drawText(QRectF(), Qt::AlignCenter, _content, &br);
    auto w = br.width() + 2 * Padding_Lr;
    if (_closeBtn != nullptr) {
        w += _closeBtn->width() + Icon_Spacing;
    }
    resize(w, br.height() + 2 * Padding_Tb);
    painter.setBrush(_palette.color(ElPalette::Background));
    QPen pen(_palette.color(ElPalette::Border));
    painter.setPen(pen);
    painter.drawRoundedRect(getDrawRect(), height() / 8.0, height() / 8.0);
    pen.setColor(_palette.color(ElPalette::Foreground));
    painter.setPen(pen);
    QRectF drawingRect(Padding_Lr, 0, br.width(), height());
    painter.drawText(drawingRect, Qt::AlignCenter, _content);
    // show close button
    if (_closeBtn != nullptr) {
        _closeBtn->move(width() - Icon_Spacing - _closeBtn->width(),
                        (height() - _closeBtn->height()) / 2);
    }
    e->accept();
}

void ElTag::mouseReleaseEvent(QMouseEvent *e)
{
    auto pos = e->pos();
    if (pos.x() >= 0 && pos.x() <= width() && pos.y() >= 0 && pos.y() <= height()) {
        emit clicked();
    }
    e->accept();
}

void ElTag::initPalette()
{
    if (type() == Default) {
        _palette.setColor(ElPalette::Background, _bg);
        _palette.setColor(ElPalette::Foreground, _fg);
        _palette.setColor(ElPalette::Border, _bd);
    } else {
        if (_effect == Light) {
            if (type() == Success)
                _palette.setColor(ElPalette::Border, QColor(225, 243, 216));
            else if (type() == Warning)
                _palette.setColor(ElPalette::Border, QColor(250, 236, 216));
            else if (type() == Info)
                _palette.setColor(ElPalette::Border, QColor(233, 233, 235));
            else if (type() == Danger)
                _palette.setColor(ElPalette::Border, QColor(253, 226, 226));
            _palette.setColor(ElPalette::Background, _theme.shallowColor());
            _palette.setColor(ElPalette::Foreground, _theme.normalColor());
        } else if (_effect == Dark) {
            _palette.setColor(ElPalette::Border, _theme.normalColor());
            _palette.setColor(ElPalette::Background, _theme.normalColor());
        } else if (_effect == Plain) {
            if (type() == Success)
                _palette.setColor(ElPalette::Border, QColor(194, 231, 176));
            else if (type() == Warning)
                _palette.setColor(ElPalette::Border, QColor(245, 218, 177));
            else if (type() == Info)
                _palette.setColor(ElPalette::Border, QColor(211, 212, 214));
            else if (type() == Danger)
                _palette.setColor(ElPalette::Border, QColor(251, 196, 196));
            _palette.setColor(ElPalette::Foreground, _theme.normalColor());
        }
    }
    if (_closeBtn != nullptr) {
        updateCloseBtn();
    }
}

QString ElTag::content() const
{
    return _content;
}

void ElTag::setContent(const QString &content)
{
    if (_content == content)
        return;
    _content = content;
}

ElTag::Type ElTag::type() const
{
    switch (_theme.type()) {
    case ElTheme::Success:
        return Success;
    case ElTheme::Warning:
        return Warning;
    case ElTheme::Information:
        return Info;
    case ElTheme::Danger:
        return Danger;
    default:
        return Default;
    }
}

void ElTag::setType(Type type)
{
    switch (type) {
    case Success:
        _theme.setType(ElTheme::Success);
        break;
    case Warning:
        _theme.setType(ElTheme::Warning);
        break;
    case Info:
        _theme.setType(ElTheme::Information);
        break;
    case Danger:
        _theme.setType(ElTheme::Danger);
        break;
    default:
        _theme.setType(ElTheme::Default);
        break;
    }
    initPalette();
}

ElTag::Effect ElTag::effect() const
{
    return _effect;
}

void ElTag::setEffect(Effect effect)
{
    if (_effect == effect)
        return;
    _effect = effect;
    switch (_effect) {
    case Light:
        _bg = ThemeColor::primaryShallowColor;
        _fg = ThemeColor::primaryColor;
        _bd = QColor(217, 236, 255);
        break;
    case Dark:
        _bg = ThemeColor::primaryColor;
        _fg = Qt::white;
        _bd = ThemeColor::primaryColor;
        break;
    case Plain:
        _bg = Qt::white;
        _fg = ThemeColor::primaryColor;
        _bd = QColor(179, 216, 255);
        break;
    default:
        break;
    }
    initPalette();
}

bool ElTag::isClosable() const
{
    return _closable;
}

void ElTag::setClosable(bool closable)
{
    if (_closable == closable)
        return;
    _closable = closable;
    if (_closable) {
        createCloseBtn();
    } else {
        delete _closeBtn;
        _closeBtn = nullptr;
    }
}

bool ElTag::isHit() const
{
    return _hit;
}

void ElTag::setHit(bool hit)
{
    if (_hit == hit)
        return;
    _hit = hit;
    // hit affects initial border color values, but not custom border values.
    if (_hit
        && (_bd == ThemeColor::primaryColor || _bd == QColor(179, 216, 255)
            || _bd == QColor(217, 236, 255)))
        _palette.setColor(ElPalette::Border, _theme.normalColor());
    else
        initPalette();
}

QColor ElTag::backgroundColor() const
{
    return _bg;
}

void ElTag::setBackgroundColor(const QColor &bgColor)
{
    if (_bg == bgColor)
        return;
    _bg = bgColor;
    initPalette();
}

QColor ElTag::foregroundColor() const
{
    return _fg;
}

void ElTag::setForegroundColor(const QColor &fgColor)
{
    if (_fg == fgColor)
        return;
    _fg = fgColor;
    initPalette();
}

QColor ElTag::borderColor() const
{
    return _bd;
}

void ElTag::setBorderColor(const QColor &bdColor)
{
    if (_bd == bdColor)
        return;
    _bd = bdColor;
    initPalette();
}

void ElTag::createCloseBtn()
{
    _closeBtn = new ElCircleButton(this);
    _closeBtn->setIcon(":/icons/close.svg", 12);
    _closeBtn->setRadius(8);
    connect(_closeBtn, &ElCircleButton::clicked, this, &ElTag::closeClicked);
    updateCloseBtn();
}

void ElTag::updateCloseBtn()
{
    auto pal = _closeBtn->palette();
    pal.setColor(ElPalette::Background, _palette.color(ElPalette::Background));
    pal.setColor(ElPalette::Foreground, _palette.color(ElPalette::Foreground));
    pal.setColor(ElPalette::Border, _palette.color(ElPalette::Background));
    bool isDark = _effect == Dark;
    pal.setColor(ElPalette::Entered, ElPalette::Background, _palette.color(ElPalette::Foreground));
    pal.setColor(ElPalette::Entered,
                 ElPalette::Foreground,
                 isDark ? _palette.color(ElPalette::Background) : Qt::white);
    pal.setColor(ElPalette::Entered, ElPalette::Border, _palette.color(ElPalette::Foreground));
    pal.setColor(ElPalette::Pressed, ElPalette::Background, _palette.color(ElPalette::Foreground));
    pal.setColor(ElPalette::Pressed,
                 ElPalette::Foreground,
                 isDark ? _palette.color(ElPalette::Background) : Qt::white);
    pal.setColor(ElPalette::Pressed, ElPalette::Border, _palette.color(ElPalette::Foreground));
    _closeBtn->setPalette(pal);
}
